package com.mlethe.library.fingerprint;

import android.content.Context;
import android.os.Build;

import androidx.annotation.RequiresApi;
import androidx.core.hardware.fingerprint.FingerprintManagerCompat;
import androidx.core.os.CancellationSignal;

import com.mlethe.library.fingerprint.callback.FingerprintCallback;
import com.mlethe.library.fingerprint.callback.IFingerprint;
import com.mlethe.library.fingerprint.entity.VerificationDialogStyle;
import com.mlethe.library.fingerprint.uitls.CipherHelper;

/**
 * Android M == 6.0
 * Created by Mlethe on 2019/7/9.
 */
@RequiresApi(api = Build.VERSION_CODES.M)
class FingerprintImplForNoDialog implements IFingerprint {

    /**
     * 指纹加密
     */
    private FingerprintManagerCompat.CryptoObject cryptoObject;
    /**
     * Android 6.0 指纹管理
     */
    private FingerprintManagerCompat fingerprintManagerCompat;
    /**
     * 用于取消扫描器的扫描动作
     */
    private CancellationSignal cancellationSignal;
    /**
     * 指向调用者的指纹回调
     */
    private FingerprintCallback fingerprintCallback;
    /**
     * 指纹验证结果回调
     */
    private FingerprintManagerCompat.AuthenticationCallback authenticationCallback = new FingerprintManagerCompat.AuthenticationCallback() {
        @Override
        public void onAuthenticationError(int errMsgId, CharSequence errString) {
            super.onAuthenticationError(errMsgId, errString);
            // errMsgId == 5 用户取消指纹验证
            if (errMsgId != 5) {
                if (fingerprintCallback != null) {
                    fingerprintCallback.onError(errString.toString());
                }
            }
        }

        @Override
        public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
            super.onAuthenticationHelp(helpMsgId, helpString);
            if (fingerprintCallback != null) {
                fingerprintCallback.onError(helpString.toString());
            }
        }

        @Override
        public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
            super.onAuthenticationSucceeded(result);
            if (fingerprintCallback != null) {
                fingerprintCallback.onSucceeded();
            }
            onDestroy();
        }

        @Override
        public void onAuthenticationFailed() {
            super.onAuthenticationFailed();
            if (fingerprintCallback != null) {
                fingerprintCallback.onFailed();
            }
        }
    };

    private static final class Holder {
        private static final FingerprintImplForNoDialog INSTANCE = new FingerprintImplForNoDialog();
    }

    private FingerprintImplForNoDialog() {
    }

    public static FingerprintImplForNoDialog getInstance() {
        FingerprintImplForNoDialog instance = Holder.INSTANCE;
        instance.createCryptoObject();
        return instance;
    }

    /**
     * 创建指纹加密
     */
    private void createCryptoObject() {
        // 指纹加密，提前进行Cipher初始化，防止指纹认证时还没有初始化完成
        try {
            if (cryptoObject == null) {
                cryptoObject = new FingerprintManagerCompat.CryptoObject(new CipherHelper().createCipher());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置回调监听
     *
     * @param callback
     */
    @Override
    public void setFingerprintCallback(FingerprintCallback callback) {
        fingerprintCallback = callback;
    }

    @Override
    public void setVerificationDialogStyle(VerificationDialogStyle verificationDialogStyle) {
    }

    /**
     * 调起指纹验证
     *
     * @param context
     */
    @Override
    public void authenticate(Context context) {
        // Android 6.0 指纹管理 实例化
        if (fingerprintManagerCompat == null) {
            fingerprintManagerCompat = FingerprintManagerCompat.from(context);
        }

        // 取消扫描，每次取消后需要重新创建新示例
        cancellationSignal = new CancellationSignal();
        cancellationSignal.setOnCancelListener(new CancellationSignal.OnCancelListener() {
            @Override
            public void onCancel() {
                if (fingerprintCallback != null) {
                    fingerprintCallback.onCancel();
                }
                onDestroy();
            }
        });
        // 调起指纹验证
        fingerprintManagerCompat.authenticate(cryptoObject, 0, cancellationSignal, authenticationCallback, null);
        // 指纹验证框
    }

    /**
     * 取消指纹识别
     */
    @Override
    public void cancel() {
        if (cancellationSignal != null && !cancellationSignal.isCanceled()) {
            cancellationSignal.cancel();
            cancellationSignal = null;
        }
    }

    /**
     * 在 Android Q，Google 提供了 Api BiometricManager.canAuthenticate() 用来检测指纹识别硬件是否可用及是否添加指纹
     * 不过尚未开放，标记为"Stub"(存根)
     * 所以暂时还是需要使用 Andorid 6.0 的 Api 进行判断
     */
    @Override
    public boolean canAuthenticate(Context context) {
        /**
         * 硬件是否支持指纹识别
         */
        if (!FingerprintManagerCompat.from(context).isHardwareDetected()) {
            if (fingerprintCallback != null) {
                fingerprintCallback.onHwUnavailable();
            }
            onDestroy();
            return false;
        }
        /**
         * 是否已添加指纹
         */
        if (!FingerprintManagerCompat.from(context).hasEnrolledFingerprints()) {
            if (fingerprintCallback != null) {
                fingerprintCallback.onNoneEnrolled();
            }
            onDestroy();
            return false;
        }
        return true;
    }

    @Override
    public void onDestroy() {
        cancellationSignal = null;
        fingerprintCallback = null;
    }
}
